/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cn.pedant.SweetAlert;

import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.Arc;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.Point;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;

/**
 * the success view
 */
public class SuccessView extends Component {
    private Paint circleBgPaint;
    private Paint paint;
    private int color = 0xffA5DC86;
    private int circleBgColor = ColorUtils.cpc(0xffffffff, 0x33A5DC86);
    private int boundWidth;
    private int boundHeight;
    private int strokeWidth = dp2px(3);

    private float dTime;

    private AnimatorValue roundAnimatorValue;

    public SuccessView(Context context) {
        this(context, null, null);
    }

    public SuccessView(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public SuccessView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        init();
    }

    private void init() {
        circleBgPaint = new Paint();
        circleBgPaint.setStrokeWidth(strokeWidth);
        circleBgPaint.setStyle(Paint.Style.STROKE_STYLE);
        circleBgPaint.setColor(new Color(circleBgColor));
        paint = new Paint();
        paint.setStrokeWidth(strokeWidth);
        paint.setStyle(Paint.Style.STROKE_STYLE);
        paint.setStrokeCap(Paint.StrokeCap.ROUND_CAP);
        paint.setColor(new Color(color));
        onDraw();
    }

    private void onDraw(){
        addDrawTask(
                (component, canvas) -> {
                    drawCircle(canvas);
                    drawTick(canvas);
                });
    }

    private void drawCircle(Canvas canvas){
        boundWidth = getWidth() - getPaddingLeft() - getPaddingRight();
        boundHeight = getWidth() - getPaddingTop() - getPaddingBottom();
        canvas.drawCircle(
                boundWidth / 2.0f,
                boundHeight / 2.0f,
                boundWidth / 2.0f - strokeWidth / 2.0f,
                circleBgPaint);

        if (dTime >= 100 && dTime <= 300) {
            canvas.drawArc(
                    new RectFloat(
                            strokeWidth / 2.0f,
                            strokeWidth / 2.0f,
                            boundWidth - strokeWidth / 2.0f,
                            boundHeight - strokeWidth / 2.0f),
                    new Arc(60, -90 * (dTime - 100) / 200, false),
                    paint);
        } else if (dTime > 300 && dTime <= 500) {
            canvas.drawArc(
                    new RectFloat(
                            strokeWidth / 2.0f,
                            strokeWidth / 2.0f,
                            boundWidth - strokeWidth / 2.0f,
                            boundHeight - strokeWidth / 2.0f),
                    new Arc(60 - 120 * (dTime - 300) / 200, -90, false),
                    paint);
        } else if (dTime > 500 && dTime <= 700) {
            canvas.drawArc(
                    new RectFloat(
                            strokeWidth / 2.0f,
                            strokeWidth / 2.0f,
                            boundWidth - strokeWidth / 2.0f,
                            boundHeight - strokeWidth / 2.0f),
                    new Arc(-60 - 90 * (dTime - 500) / 200, -90 + 90 * (dTime - 500) / 200, false),
                    paint);
        }
    }

    private void drawTick(Canvas canvas){
        if (dTime > 500) {
            float radius = (boundWidth - strokeWidth) / 2.0f;
            float startX;
            float startY;
            float centerX;
            float centerY;
            float endX;
            float endY;
            float toMove;
            float toMove2;
            startX = radius + strokeWidth / 2.0f - (float) Math.cos(Math.toRadians(30)) * radius;
            startY = radius / 2 + strokeWidth / 2.0f;
            centerX = boundWidth / 2.0f;
            centerY = startY + (centerX - startX);
            endX = boundWidth - startX;
            endY = startY;
            toMove = centerX - startX;
            toMove2 = toMove * 0.35f;
            if (dTime > 500 && dTime <= 700) {
                canvas.drawLine(
                        new Point(startX, startY),
                        new Point(startX + (dTime - 500) / 200 * toMove,startY + (dTime - 500) / 200 * toMove),
                        paint);
            }
            if (dTime > 700 && dTime <= 900) {
                canvas.drawLine(
                        new Point(startX + (dTime - 700) / 200 * toMove,startY + (dTime - 700) / 200 * toMove),
                        new Point(centerX, centerY),
                        paint);
                canvas.drawLine(
                        new Point(centerX, centerY),
                        new Point(centerX + (dTime - 700) / 200 * toMove,centerY - (dTime - 700) / 200 * toMove),
                        paint);
            }
            if (dTime > 900) {
                canvas.drawLine(
                        new Point(centerX, centerY),
                        new Point(endX - (dTime - 900) / 100 * toMove2,endY + (dTime - 900) / 100 * toMove2),
                        paint);
                canvas.drawLine(
                        new Point(centerX, centerY),
                        new Point(centerX - (dTime - 900) / 100 * toMove2,centerY - (dTime - 900) / 100 * toMove2),
                        paint);
            }
        }
    }

    /**
     * start animator
     */
    public void startAnimator() {
        if (roundAnimatorValue == null) {
            roundAnimatorValue = new AnimatorValue();
            roundAnimatorValue.setDuration(750);
            roundAnimatorValue.setValueUpdateListener(
                    (animatorValue, v) -> {
                        dTime = 1000 * v;
                        getContext()
                                .getUITaskDispatcher()
                                .asyncDispatch(
                                        () -> invalidate());
                    });
        }
        roundAnimatorValue.start();
    }

    /**
     * set visibility
     *
     * @param visibility the visibility
     */
    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
        if (visibility != Component.VISIBLE) {
            if (roundAnimatorValue != null && roundAnimatorValue.isRunning()) {
                roundAnimatorValue.stop();
            }
        }
    }

    private int dp2px(float dp) {
        return (int) (getResourceManager().getDeviceCapability().screenDensity / 160 * dp);
    }
}
